//! Type checker for NRC language

use crate::ast::*;
use crate::error::Result;
use crate::semantic::symbol_table::SymbolTable;

/// Type checker for NRC language
pub struct TypeChecker {
    /// Symbol table for type information
    symbol_table: SymbolTable,
    /// Current scope depth
    #[allow(dead_code)]
    scope_depth: usize,
}

impl TypeChecker {
    /// Create a new type checker
    pub fn new(symbol_table: SymbolTable) -> Self {
        Self {
            symbol_table,
            scope_depth: 0,
        }
    }

    /// Check if the type checker is empty (no symbols)
    pub fn is_empty(&self) -> bool {
        self.symbol_table.is_empty()
    }

    /// Check types in a program
    pub fn check_program(&mut self, program: &Program) -> Result<()> {
        for declaration in &program.declarations {
            self.check_declaration(declaration)?;
        }
        Ok(())
    }

    /// Check types in a declaration
    fn check_declaration(&mut self, declaration: &Declaration) -> Result<()> {
        match declaration {
            Declaration::Function(func) => self.check_function(func)?,
            Declaration::Variable(var) => self.check_variable(var)?,
            Declaration::Constant(const_) => self.check_constant(const_)?,
            Declaration::Type(type_) => self.check_type_declaration(type_)?,
            Declaration::Struct(struct_) => self.check_struct(struct_)?,
            Declaration::Trait(_trait) => {
                // TODO: Check trait declaration
            }
            Declaration::TraitImpl(_trait_impl) => {
                // TODO: Check trait implementation
            }
            Declaration::Import(import) => self.check_import(import)?,
            Declaration::Impl(impl_) => self.check_impl(impl_)?,
            Declaration::Enum(_enum) => {
                // For now, enums don't need type checking
            }
        }
        Ok(())
    }

    /// Check types in a function
    fn check_function(&mut self, _func: &FunctionDecl) -> Result<()> {
        // TODO: Implement function type checking
        Ok(())
    }

    /// Check types in a variable
    fn check_variable(&mut self, _var: &VariableDecl) -> Result<()> {
        // TODO: Implement variable type checking
        Ok(())
    }

    /// Check types in a constant
    fn check_constant(&mut self, _const_: &ConstantDecl) -> Result<()> {
        // TODO: Implement constant type checking
        Ok(())
    }

    /// Check types in a type declaration
    fn check_type_declaration(&mut self, _type_: &TypeDecl) -> Result<()> {
        // TODO: Implement type declaration checking
        Ok(())
    }

    /// Check types in a struct
    fn check_struct(&mut self, _struct_: &StructDecl) -> Result<()> {
        // TODO: Implement struct type checking
        Ok(())
    }

    /// Check types in an import
    fn check_import(&mut self, _import: &ImportDecl) -> Result<()> {
        // TODO: Implement import type checking
        Ok(())
    }

    fn check_impl(&mut self, impl_: &ImplDecl) -> Result<()> {
        // Check types for each method in the impl block
        for method in &impl_.methods {
            self.check_function(method)?;
        }

        Ok(())
    }
}
